package tomasulo.unit;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Queue;

public class FLOS {
	
	private Queue<Instr> insQueue = null;
	private boolean upToDate = true;
	private Iterator<Instr> myIter = null;
	private final Instr NOOP_INS = new Instr("NOOP");
	
	private Instr resolveIns(String ins) {
		Instr ret = new Instr(ins);
		String insPart[] = ins.split("[ \t]*[, \t][ \t]*");
		if (insPart[0].equals("ADDD")) {
			ret.op = Instr.OP.ADDD;
			ret.op0 = Integer.parseInt(insPart[1].substring(1));
			ret.op1 = Integer.parseInt(insPart[2].substring(1));
			ret.op2 = Integer.parseInt(insPart[3].substring(1));
		} else if (insPart[0].equals("SUBD")) {
			ret.op = Instr.OP.SUBD;
			ret.op0 = Integer.parseInt(insPart[1].substring(1));
			ret.op1 = Integer.parseInt(insPart[2].substring(1));
			ret.op2 = Integer.parseInt(insPart[3].substring(1));
		} else if (insPart[0].equals("MULTD")) {
			ret.op = Instr.OP.MULTD;
			ret.op0 = Integer.parseInt(insPart[1].substring(1));
			ret.op1 = Integer.parseInt(insPart[2].substring(1));
			ret.op2 = Integer.parseInt(insPart[3].substring(1));
		} else if (insPart[0].equals("DIVD")) {
			ret.op = Instr.OP.DIVD;
			ret.op0 = Integer.parseInt(insPart[1].substring(1));
			ret.op1 = Integer.parseInt(insPart[2].substring(1));
			ret.op2 = Integer.parseInt(insPart[3].substring(1));
		} else if (insPart[0].equals("LD")) {
			ret.op = Instr.OP.LD;
			ret.op0 = Integer.parseInt(insPart[1].substring(1));
			if (insPart[2].startsWith("0x") || insPart[2].startsWith("0X")) {
				ret.op1 = Integer.parseInt(insPart[2].substring(2), 16);
			} else {
				ret.op1 = Integer.parseInt(insPart[2]);
			}
		} else if (insPart[0].equals("ST")) {
			ret.op = Instr.OP.ST;
			ret.op0 = Integer.parseInt(insPart[1].substring(1));
			if (insPart[2].startsWith("0x") || insPart[2].startsWith("0X")) {
				ret.op1 = Integer.parseInt(insPart[2].substring(2), 16);
			} else {
				ret.op1 = Integer.parseInt(insPart[2]);
			}
		} else {
			ret.op = Instr.OP.NOOP;
		}
		return ret;
	}
	
	public FLOS() {
		insQueue = new LinkedList<Instr>();
	}
	
	public boolean isUpToDate() {
		return upToDate;
	}
	
	public void setUpToDate(boolean isUpToDate) {
		this.upToDate = isUpToDate;
	}
	
	public void reset() {
		for (Instr i : insQueue)
			i.reset();
		myIter = insQueue.iterator();
	}
	
	public void loadInstr(File f) {
		upToDate = false;
		insQueue.clear();
		try {
			BufferedReader reader = new BufferedReader(new FileReader(f));
			String ins;
			while ((ins = reader.readLine()) != null) {
				if (ins.equals("")) continue;
				insQueue.add(resolveIns(ins));
			}
			reader.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		myIter = insQueue.iterator();
	}
	
	public Iterator<Instr> getIterator() {
		return insQueue.iterator();
	}
	
	public Instr nextInstr() {
		if (myIter.hasNext()) {
			return myIter.next();
		} else {
			return NOOP_INS;
		}
	}
	
}
